@@ -43,70 +43,105 @@ static void *allocateTrailingInst(SILFunction &F, CountTypes... counts) {
43
43
alignof (Inst));
44
44
}
45
45
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
+
46
75
// / Collect root open archetypes from a given type into \p RootOpenedArchetypes.
47
76
// / \p RootOpenedArchetypes is being used as a set. We don't use a real set type
48
77
// / 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)
53
80
return ;
54
- if (Ty ->hasDynamicSelfType ())
81
+ if (type ->hasDynamicSelfType ())
55
82
hasDynamicSelf = true ;
56
- if (!Ty ->hasOpenedExistential ())
83
+ if (!type ->hasOpenedExistential ())
57
84
return ;
58
- Ty .visit ([&](CanType t) {
85
+ type .visit ([&](CanType t) {
59
86
if (const auto opened = dyn_cast<OpenedArchetypeType>(t)) {
60
87
const auto root = opened.getRoot ();
61
88
62
89
// Add this root opened archetype if it was not seen yet.
63
90
// We don't use a set here, because the number of open archetypes
64
91
// is usually very small and using a real set may introduce too
65
92
// 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);
69
96
}
70
97
});
71
98
}
72
99
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
+ }
79
109
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) {
81
116
SILValue def = F.getModule ().getRootOpenedArchetypeDef (archetype, &F);
82
117
assert (def->getFunction () == &F &&
83
118
" 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);
85
128
}
86
129
if (hasDynamicSelf)
87
- TypeDependentOperands .push_back (F.getDynamicSelfMetadata ());
130
+ operands .push_back (F.getDynamicSelfMetadata ());
88
131
}
89
132
90
133
// / Collects all root opened archetypes from a type and a substitution list, and
91
134
// / forms a corresponding list of operands.
92
135
// / We need to know the number of root opened archetypes to estimate the number
93
136
// / of corresponding operands for the instruction being formed, because we need
94
137
// / to reserve enough memory for these operands.
138
+ template <class ... Sources>
95
139
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);
110
145
}
111
146
112
147
// ===----------------------------------------------------------------------===//
@@ -284,10 +319,7 @@ AllocRefInst *AllocRefInst::create(SILDebugLocation Loc, SILFunction &F,
284
319
assert (!objc || ElementTypes.empty ());
285
320
SmallVector<SILValue, 8 > AllOperands (ElementCountOperands.begin (),
286
321
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);
291
323
auto Size = totalSizeToAlloc<swift::Operand, SILType>(AllOperands.size (),
292
324
ElementTypes.size ());
293
325
auto Buffer = F.getModule ().allocateInst (Size, alignof (AllocRefInst));
@@ -304,10 +336,7 @@ AllocRefDynamicInst::create(SILDebugLocation DebugLoc, SILFunction &F,
304
336
SmallVector<SILValue, 8 > AllOperands (ElementCountOperands.begin (),
305
337
ElementCountOperands.end ());
306
338
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);
311
340
auto Size = totalSizeToAlloc<swift::Operand, SILType>(AllOperands.size (),
312
341
ElementTypes.size ());
313
342
auto Buffer = F.getModule ().allocateInst (Size, alignof (AllocRefDynamicInst));
@@ -1249,14 +1278,13 @@ UncheckedRefCastAddrInst *
1249
1278
UncheckedRefCastAddrInst::create (SILDebugLocation Loc, SILValue src,
1250
1279
CanType srcType, SILValue dest, CanType targetType, SILFunction &F) {
1251
1280
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);
1255
1283
unsigned size =
1256
- totalSizeToAlloc<swift::Operand>(2 + TypeDependentOperands .size ());
1284
+ totalSizeToAlloc<swift::Operand>(2 + allOperands .size ());
1257
1285
void *Buffer = Mod.allocateInst (size, alignof (UncheckedRefCastAddrInst));
1258
1286
return ::new (Buffer) UncheckedRefCastAddrInst (Loc, src, srcType,
1259
- dest, targetType, TypeDependentOperands );
1287
+ dest, targetType, allOperands );
1260
1288
}
1261
1289
1262
1290
UnconditionalCheckedCastAddrInst::UnconditionalCheckedCastAddrInst (
@@ -1269,14 +1297,13 @@ UnconditionalCheckedCastAddrInst *
1269
1297
UnconditionalCheckedCastAddrInst::create (SILDebugLocation Loc, SILValue src,
1270
1298
CanType srcType, SILValue dest, CanType targetType, SILFunction &F) {
1271
1299
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);
1275
1302
unsigned size =
1276
- totalSizeToAlloc<swift::Operand>(2 + TypeDependentOperands .size ());
1303
+ totalSizeToAlloc<swift::Operand>(2 + allOperands .size ());
1277
1304
void *Buffer = Mod.allocateInst (size, alignof (UnconditionalCheckedCastAddrInst));
1278
1305
return ::new (Buffer) UnconditionalCheckedCastAddrInst (Loc, src, srcType,
1279
- dest, targetType, TypeDependentOperands );
1306
+ dest, targetType, allOperands );
1280
1307
}
1281
1308
1282
1309
CheckedCastAddrBranchInst::CheckedCastAddrBranchInst (
@@ -1300,14 +1327,13 @@ CheckedCastAddrBranchInst::create(SILDebugLocation DebugLoc,
1300
1327
ProfileCounter Target1Count, ProfileCounter Target2Count,
1301
1328
SILFunction &F) {
1302
1329
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);
1306
1332
unsigned size =
1307
- totalSizeToAlloc<swift::Operand>(2 + TypeDependentOperands .size ());
1333
+ totalSizeToAlloc<swift::Operand>(2 + allOperands .size ());
1308
1334
void *Buffer = Mod.allocateInst (size, alignof (CheckedCastAddrBranchInst));
1309
1335
return ::new (Buffer) CheckedCastAddrBranchInst (DebugLoc, consumptionKind,
1310
- src, srcType, dest, targetType, TypeDependentOperands ,
1336
+ src, srcType, dest, targetType, allOperands ,
1311
1337
successBB, failureBB, Target1Count, Target2Count);
1312
1338
}
1313
1339
0 commit comments