@@ -1034,6 +1034,17 @@ static bool scanUsesForEscapesAndMutations(Operand *Op,
1034
1034
return isPartialApplyNonEscapingUser (Op, PAI, State);
1035
1035
}
1036
1036
1037
+ // A mark_dependence user on a partial_apply is safe.
1038
+ if (auto *MD = dyn_cast<MarkDependenceInst>(User)) {
1039
+ if (MD->getBase () == Op->get ()) {
1040
+ auto parent = MD->getValue ();
1041
+ while ((MD = dyn_cast<MarkDependenceInst>(parent))) {
1042
+ parent = MD->getValue ();
1043
+ }
1044
+ return isa<PartialApplyInst>(parent);
1045
+ }
1046
+ }
1047
+
1037
1048
if (auto *PBI = dyn_cast<ProjectBoxInst>(User)) {
1038
1049
// It is assumed in later code that we will only have 1 project_box. This
1039
1050
// can be seen since there is no code for reasoning about multiple
@@ -1198,6 +1209,26 @@ static SILValue getOrCreateProjectBoxHelper(SILValue PartialOperand) {
1198
1209
return B.createProjectBox (Box->getLoc (), Box, 0 );
1199
1210
}
1200
1211
1212
+ // / Change the base in mark_dependence.
1213
+ static void
1214
+ mapMarkDependenceArguments (SingleValueInstruction *root,
1215
+ llvm::DenseMap<SILValue, SILValue> &map) {
1216
+ for (auto *Use : root->getUses ()) {
1217
+ if (auto *MD = dyn_cast<MarkDependenceInst>(Use->getUser ())) {
1218
+ mapMarkDependenceArguments (MD, map);
1219
+ auto iter = map.find (MD->getBase ());
1220
+ if (iter != map.end ()) {
1221
+ MD->setBase (iter->second );
1222
+ }
1223
+ // Remove mark_dependence on trivial values.
1224
+ if (MD->getBase ()->getType ().isTrivial (MD->getModule ())) {
1225
+ MD->replaceAllUsesWith (MD->getValue ());
1226
+ MD->eraseFromParent ();
1227
+ }
1228
+ }
1229
+ }
1230
+ }
1231
+
1201
1232
// / Given a partial_apply instruction and a set of promotable indices,
1202
1233
// / clone the closure with the promoted captures and replace the partial_apply
1203
1234
// / with a partial_apply of the new closure, fixing up reference counting as
@@ -1236,6 +1267,8 @@ processPartialApplyInst(SILOptFunctionBuilder &FuncBuilder,
1236
1267
unsigned OpCount = PAI->getNumOperands () - PAI->getNumTypeDependentOperands ();
1237
1268
SmallVector<SILValue, 16 > Args;
1238
1269
auto NumIndirectResults = calleeConv.getNumIndirectSILResults ();
1270
+ llvm::DenseMap<SILValue, SILValue> capturedMap;
1271
+ llvm::SmallSet<SILValue, 16 > newCaptures;
1239
1272
for (; OpNo != OpCount; ++OpNo) {
1240
1273
unsigned Index = OpNo - 1 + FirstIndex;
1241
1274
if (!PromotableIndices.count (Index)) {
@@ -1250,8 +1283,18 @@ processPartialApplyInst(SILOptFunctionBuilder &FuncBuilder,
1250
1283
SILValue Addr = getOrCreateProjectBoxHelper (Box);
1251
1284
1252
1285
auto &typeLowering = M.getTypeLowering (Addr->getType ());
1253
- Args.push_back (
1254
- typeLowering.emitLoadOfCopy (B, PAI->getLoc (), Addr, IsNotTake));
1286
+ auto newCaptured =
1287
+ typeLowering.emitLoadOfCopy (B, PAI->getLoc (), Addr, IsNotTake);
1288
+ Args.push_back (newCaptured);
1289
+
1290
+ capturedMap[Box] = newCaptured;
1291
+ newCaptures.insert (newCaptured);
1292
+
1293
+ // A partial_apply [stack] does not own the captured argument but we must
1294
+ // destroy the projected object. We will do so after having created the new
1295
+ // partial_apply below.
1296
+ if (PAI->isOnStack ())
1297
+ continue ;
1255
1298
1256
1299
// Cleanup the captured argument.
1257
1300
//
@@ -1268,14 +1311,30 @@ processPartialApplyInst(SILOptFunctionBuilder &FuncBuilder,
1268
1311
// Create a new partial apply with the new arguments.
1269
1312
auto *NewPAI = B.createPartialApply (
1270
1313
PAI->getLoc (), FnVal, PAI->getSubstitutionMap (), Args,
1271
- PAI->getType ().getAs <SILFunctionType>()->getCalleeConvention ());
1314
+ PAI->getType ().getAs <SILFunctionType>()->getCalleeConvention (),
1315
+ PAI->isOnStack ());
1272
1316
PAI->replaceAllUsesWith (NewPAI);
1273
1317
PAI->eraseFromParent ();
1274
1318
if (FRI->use_empty ()) {
1275
1319
FRI->eraseFromParent ();
1276
1320
// TODO: If this is the last use of the closure, and if it has internal
1277
1321
// linkage, we should remove it from the SILModule now.
1278
1322
}
1323
+
1324
+ if (NewPAI->isOnStack ()) {
1325
+ // Insert destroy's of new captured arguments.
1326
+ for (auto *Use : NewPAI->getUses ()) {
1327
+ if (auto *DS = dyn_cast<DeallocStackInst>(Use->getUser ())) {
1328
+ B.setInsertionPoint (std::next (SILBasicBlock::iterator (DS)));
1329
+ insertDestroyOfCapturedArguments (NewPAI, B, [&](SILValue arg) -> bool {
1330
+ return newCaptures.count (arg);
1331
+ });
1332
+ }
1333
+ }
1334
+ // Map the mark dependence arguments.
1335
+ mapMarkDependenceArguments (NewPAI, capturedMap);
1336
+ }
1337
+
1279
1338
return ClonedFn;
1280
1339
}
1281
1340
0 commit comments