@@ -1017,9 +1017,8 @@ class AllocOptimize {
1017
1017
bool promoteLoad (SILInstruction *Inst);
1018
1018
void promoteDestroyAddr (DestroyAddrInst *DAI,
1019
1019
MutableArrayRef<AvailableValue> Values);
1020
- bool
1021
- canPromoteDestroyAddr (DestroyAddrInst *DAI,
1022
- llvm::SmallVectorImpl<AvailableValue> &AvailableValues);
1020
+ bool canPromoteDestroyAddr (DestroyAddrInst *DAI,
1021
+ SmallVectorImpl<AvailableValue> &AvailableValues);
1023
1022
1024
1023
bool tryToRemoveDeadAllocation ();
1025
1024
};
@@ -1149,8 +1148,7 @@ bool AllocOptimize::promoteLoad(SILInstruction *Inst) {
1149
1148
1150
1149
// / Return true if we can promote the given destroy.
1151
1150
bool AllocOptimize::canPromoteDestroyAddr (
1152
- DestroyAddrInst *DAI,
1153
- llvm::SmallVectorImpl<AvailableValue> &AvailableValues) {
1151
+ DestroyAddrInst *DAI, SmallVectorImpl<AvailableValue> &AvailableValues) {
1154
1152
SILValue Address = DAI->getOperand ();
1155
1153
1156
1154
// We cannot promote destroys of address-only types, because we can't expose
@@ -1224,8 +1222,49 @@ void AllocOptimize::promoteDestroyAddr(
1224
1222
DAI->eraseFromParent ();
1225
1223
}
1226
1224
1227
- // / tryToRemoveDeadAllocation - If the allocation is an autogenerated allocation
1228
- // / that is only stored to (after load promotion) then remove it completely.
1225
+ namespace {
1226
+
1227
+ struct DestroyAddrPromotionState {
1228
+ ArrayRef<SILInstruction *> destroys;
1229
+ SmallVector<unsigned , 8 > destroyAddrIndices;
1230
+ SmallVector<AvailableValue, 32 > availableValueList;
1231
+ SmallVector<unsigned , 8 > availableValueStartOffsets;
1232
+
1233
+ DestroyAddrPromotionState (ArrayRef<SILInstruction *> destroys)
1234
+ : destroys(destroys) {}
1235
+
1236
+ unsigned size () const {
1237
+ return destroyAddrIndices.size ();
1238
+ }
1239
+
1240
+ void initializeForDestroyAddr (unsigned destroyAddrIndex) {
1241
+ availableValueStartOffsets.push_back (availableValueList.size ());
1242
+ destroyAddrIndices.push_back (destroyAddrIndex);
1243
+ }
1244
+
1245
+ std::pair<DestroyAddrInst *, MutableArrayRef<AvailableValue>>
1246
+ getData (unsigned index) {
1247
+ unsigned destroyAddrIndex = destroyAddrIndices[index];
1248
+ unsigned startOffset = availableValueStartOffsets[index];
1249
+ unsigned count;
1250
+
1251
+ if ((availableValueStartOffsets.size () - 1 ) != index) {
1252
+ count = availableValueStartOffsets[index + 1 ] - startOffset;
1253
+ } else {
1254
+ count = availableValueList.size () - startOffset;
1255
+ }
1256
+
1257
+ MutableArrayRef<AvailableValue> values (&availableValueList[startOffset],
1258
+ count);
1259
+ auto *dai = cast<DestroyAddrInst>(destroys[destroyAddrIndex]);
1260
+ return {dai, values};
1261
+ }
1262
+ };
1263
+
1264
+ } // end anonymous namespace
1265
+
1266
+ // / If the allocation is an autogenerated allocation that is only stored to
1267
+ // / (after load promotion) then remove it completely.
1229
1268
bool AllocOptimize::tryToRemoveDeadAllocation () {
1230
1269
assert ((isa<AllocBoxInst>(TheMemory) || isa<AllocStackInst>(TheMemory)) &&
1231
1270
" Unhandled allocation case" );
@@ -1236,29 +1275,30 @@ bool AllocOptimize::tryToRemoveDeadAllocation() {
1236
1275
// 1. They are in a transparent function.
1237
1276
// 2. They are in a normal function, but didn't come from a VarDecl, or came
1238
1277
// from one that was autogenerated or inlined from a transparent function.
1239
- SILLocation Loc = TheMemory->getLoc ();
1278
+ SILLocation loc = TheMemory->getLoc ();
1240
1279
if (!TheMemory->getFunction ()->isTransparent () &&
1241
- Loc .getAsASTNode <VarDecl>() && !Loc .isAutoGenerated () &&
1242
- !Loc .is <MandatoryInlinedLocation>())
1280
+ loc .getAsASTNode <VarDecl>() && !loc .isAutoGenerated () &&
1281
+ !loc .is <MandatoryInlinedLocation>())
1243
1282
return false ;
1244
1283
1245
1284
// Check the uses list to see if there are any non-store uses left over after
1246
1285
// load promotion and other things PMO does.
1247
- for (auto &U : Uses) {
1286
+ for (auto &u : Uses) {
1248
1287
// Ignore removed instructions.
1249
- if (U.Inst == nullptr ) continue ;
1288
+ if (u.Inst == nullptr )
1289
+ continue ;
1250
1290
1251
- switch (U .Kind ) {
1291
+ switch (u .Kind ) {
1252
1292
case PMOUseKind::Assign:
1253
1293
case PMOUseKind::PartialStore:
1254
1294
case PMOUseKind::InitOrAssign:
1255
1295
break ; // These don't prevent removal.
1256
1296
case PMOUseKind::Initialization:
1257
- if (!isa<ApplyInst>(U .Inst ) &&
1297
+ if (!isa<ApplyInst>(u .Inst ) &&
1258
1298
// A copy_addr that is not a take affects the retain count
1259
1299
// of the source.
1260
- (!isa<CopyAddrInst>(U .Inst ) ||
1261
- cast<CopyAddrInst>(U .Inst )->isTakeOfSrc ()))
1300
+ (!isa<CopyAddrInst>(u .Inst ) ||
1301
+ cast<CopyAddrInst>(u .Inst )->isTakeOfSrc ()))
1262
1302
break ;
1263
1303
// FALL THROUGH.
1264
1304
LLVM_FALLTHROUGH;
@@ -1267,7 +1307,8 @@ bool AllocOptimize::tryToRemoveDeadAllocation() {
1267
1307
case PMOUseKind::InOutUse:
1268
1308
case PMOUseKind::Escape:
1269
1309
LLVM_DEBUG (llvm::dbgs () << " *** Failed to remove autogenerated alloc: "
1270
- " kept alive by: " << *U.Inst );
1310
+ " kept alive by: "
1311
+ << *u.Inst );
1271
1312
return false ; // These do prevent removal.
1272
1313
}
1273
1314
}
@@ -1289,53 +1330,39 @@ bool AllocOptimize::tryToRemoveDeadAllocation() {
1289
1330
1290
1331
// Otherwise removing the deallocation will drop any releases. Check that
1291
1332
// there is nothing preventing removal.
1292
- llvm::SmallVector<unsigned , 8 > DestroyAddrIndices;
1293
- llvm::SmallVector<AvailableValue, 32 > AvailableValueList;
1294
- llvm::SmallVector<unsigned , 8 > AvailableValueStartOffsets;
1333
+ DestroyAddrPromotionState state (Releases);
1295
1334
1296
- for (auto P : llvm::enumerate (Releases)) {
1297
- auto *R = P .value ();
1298
- if (R == nullptr )
1335
+ for (auto p : llvm::enumerate (Releases)) {
1336
+ auto *r = p .value ();
1337
+ if (r == nullptr )
1299
1338
continue ;
1300
1339
1301
1340
// We stash all of the destroy_addr that we see.
1302
- if (auto *DAI = dyn_cast<DestroyAddrInst>(R )) {
1303
- AvailableValueStartOffsets. push_back (AvailableValueList. size () );
1341
+ if (auto *dai = dyn_cast<DestroyAddrInst>(r )) {
1342
+ state. initializeForDestroyAddr (p. index () /* destroyAddrIndex */ );
1304
1343
// Make sure we can actually promote this destroy addr. If we can not,
1305
1344
// then we must bail. In order to not gather available values twice, we
1306
1345
// gather the available values here that we will use to promote the
1307
1346
// values.
1308
- if (!canPromoteDestroyAddr (DAI, AvailableValueList ))
1347
+ if (!canPromoteDestroyAddr (dai, state. availableValueList ))
1309
1348
return false ;
1310
- DestroyAddrIndices.push_back (P.index ());
1311
1349
continue ;
1312
1350
}
1313
1351
1314
1352
LLVM_DEBUG (llvm::dbgs ()
1315
1353
<< " *** Failed to remove autogenerated non-trivial alloc: "
1316
1354
" kept alive by release: "
1317
- << *R );
1355
+ << *r );
1318
1356
return false ;
1319
1357
}
1320
1358
1321
1359
// If we reached this point, we can promote all of our destroy_addr.
1322
- for (auto P : llvm::enumerate (DestroyAddrIndices)) {
1323
- unsigned DestroyAddrIndex = P.value ();
1324
- unsigned AvailableValueIndex = P.index ();
1325
- unsigned StartOffset = AvailableValueStartOffsets[AvailableValueIndex];
1326
- unsigned Count;
1327
-
1328
- if ((AvailableValueStartOffsets.size () - 1 ) != AvailableValueIndex) {
1329
- Count = AvailableValueStartOffsets[AvailableValueIndex + 1 ] - StartOffset;
1330
- } else {
1331
- Count = AvailableValueList.size () - StartOffset;
1332
- }
1333
-
1334
- MutableArrayRef<AvailableValue> Values (&AvailableValueList[StartOffset],
1335
- Count);
1336
- auto *DAI = cast<DestroyAddrInst>(Releases[DestroyAddrIndex]);
1337
- promoteDestroyAddr (DAI, Values);
1338
- Releases[DestroyAddrIndex] = nullptr ;
1360
+ for (unsigned i : range (state.size ())) {
1361
+ DestroyAddrInst *dai;
1362
+ MutableArrayRef<AvailableValue> values;
1363
+ std::tie (dai, values) = state.getData (i);
1364
+ promoteDestroyAddr (dai, values);
1365
+ // We do not need to unset releases, since we are going to exit here.
1339
1366
}
1340
1367
1341
1368
LLVM_DEBUG (llvm::dbgs () << " *** Removing autogenerated non-trivial alloc: "
0 commit comments