@@ -287,108 +287,9 @@ llvm::cl::opt<bool> DisableMoveOnlyAddressCheckerLifetimeExtension(
287
287
" move-only values." ));
288
288
289
289
// ===----------------------------------------------------------------------===//
290
- // MARK: Memory Utilities
290
+ // MARK: Utilities
291
291
// ===----------------------------------------------------------------------===//
292
292
293
- static bool memInstMustInitialize (Operand *memOper) {
294
- SILValue address = memOper->get ();
295
-
296
- SILInstruction *memInst = memOper->getUser ();
297
-
298
- switch (memInst->getKind ()) {
299
- default :
300
- return false ;
301
-
302
- case SILInstructionKind::CopyAddrInst: {
303
- auto *CAI = cast<CopyAddrInst>(memInst);
304
- return CAI->getDest () == address && CAI->isInitializationOfDest ();
305
- }
306
- case SILInstructionKind::ExplicitCopyAddrInst: {
307
- auto *CAI = cast<ExplicitCopyAddrInst>(memInst);
308
- return CAI->getDest () == address && CAI->isInitializationOfDest ();
309
- }
310
- case SILInstructionKind::MarkUnresolvedMoveAddrInst: {
311
- return cast<MarkUnresolvedMoveAddrInst>(memInst)->getDest () == address;
312
- }
313
- case SILInstructionKind::InitExistentialAddrInst:
314
- case SILInstructionKind::InitEnumDataAddrInst:
315
- case SILInstructionKind::InjectEnumAddrInst:
316
- return true ;
317
-
318
- case SILInstructionKind::BeginApplyInst:
319
- case SILInstructionKind::TryApplyInst:
320
- case SILInstructionKind::ApplyInst: {
321
- FullApplySite applySite (memInst);
322
- return applySite.isIndirectResultOperand (*memOper);
323
- }
324
- case SILInstructionKind::StoreInst: {
325
- auto qual = cast<StoreInst>(memInst)->getOwnershipQualifier ();
326
- return qual == StoreOwnershipQualifier::Init ||
327
- qual == StoreOwnershipQualifier::Trivial;
328
- }
329
-
330
- #define NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE (Name, ...) \
331
- case SILInstructionKind::Store##Name##Inst: \
332
- return cast<Store##Name##Inst>(memInst)->isInitializationOfDest ();
333
- #include " swift/AST/ReferenceStorage.def"
334
- }
335
- }
336
-
337
- static bool memInstMustReinitialize (Operand *memOper) {
338
- SILValue address = memOper->get ();
339
-
340
- SILInstruction *memInst = memOper->getUser ();
341
-
342
- switch (memInst->getKind ()) {
343
- default :
344
- return false ;
345
-
346
- case SILInstructionKind::CopyAddrInst: {
347
- auto *CAI = cast<CopyAddrInst>(memInst);
348
- return CAI->getDest () == address && !CAI->isInitializationOfDest ();
349
- }
350
- case SILInstructionKind::ExplicitCopyAddrInst: {
351
- auto *CAI = cast<ExplicitCopyAddrInst>(memInst);
352
- return CAI->getDest () == address && !CAI->isInitializationOfDest ();
353
- }
354
- case SILInstructionKind::YieldInst: {
355
- auto *yield = cast<YieldInst>(memInst);
356
- return yield->getYieldInfoForOperand (*memOper).isIndirectInOut ();
357
- }
358
- case SILInstructionKind::BeginApplyInst:
359
- case SILInstructionKind::TryApplyInst:
360
- case SILInstructionKind::ApplyInst: {
361
- FullApplySite applySite (memInst);
362
- return applySite.getArgumentOperandConvention (*memOper).isInoutConvention ();
363
- }
364
- case SILInstructionKind::StoreInst:
365
- return cast<StoreInst>(memInst)->getOwnershipQualifier () ==
366
- StoreOwnershipQualifier::Assign;
367
-
368
- #define NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE (Name, ...) \
369
- case SILInstructionKind::Store##Name##Inst: \
370
- return !cast<Store##Name##Inst>(memInst)->isInitializationOfDest ();
371
- #include " swift/AST/ReferenceStorage.def"
372
- }
373
- }
374
-
375
- // / Is this a reinit instruction that we know how to convert into its init form.
376
- static bool isReinitToInitConvertibleInst (SILInstruction *memInst) {
377
- switch (memInst->getKind ()) {
378
- default :
379
- return false ;
380
-
381
- case SILInstructionKind::CopyAddrInst: {
382
- auto *cai = cast<CopyAddrInst>(memInst);
383
- return !cai->isInitializationOfDest ();
384
- }
385
- case SILInstructionKind::StoreInst: {
386
- auto *si = cast<StoreInst>(memInst);
387
- return si->getOwnershipQualifier () == StoreOwnershipQualifier::Assign;
388
- }
389
- }
390
- }
391
-
392
293
static void insertDebugValueBefore (SILInstruction *insertPt,
393
294
DebugVarCarryingInst debugVar,
394
295
llvm::function_ref<SILValue ()> operand) {
@@ -432,47 +333,20 @@ static void convertMemoryReinitToInitForm(SILInstruction *memInst,
432
333
[&]{ return debugVar.getOperandForDebugValueClone (); });
433
334
}
434
335
435
- static bool memInstMustConsume (Operand *memOper) {
436
- SILValue address = memOper->get ();
437
-
438
- SILInstruction *memInst = memOper->getUser ();
439
-
440
- // FIXME: drop_deinit must be handled here!
336
+ // / Is this a reinit instruction that we know how to convert into its init form.
337
+ static bool isReinitToInitConvertibleInst (SILInstruction *memInst) {
441
338
switch (memInst->getKind ()) {
442
339
default :
443
340
return false ;
444
341
445
342
case SILInstructionKind::CopyAddrInst: {
446
- auto *CAI = cast<CopyAddrInst>(memInst);
447
- return (CAI->getSrc () == address && CAI->isTakeOfSrc ()) ||
448
- (CAI->getDest () == address && !CAI->isInitializationOfDest ());
449
- }
450
- case SILInstructionKind::ExplicitCopyAddrInst: {
451
- auto *CAI = cast<ExplicitCopyAddrInst>(memInst);
452
- return (CAI->getSrc () == address && CAI->isTakeOfSrc ()) ||
453
- (CAI->getDest () == address && !CAI->isInitializationOfDest ());
454
- }
455
- case SILInstructionKind::BeginApplyInst:
456
- case SILInstructionKind::TryApplyInst:
457
- case SILInstructionKind::ApplyInst: {
458
- FullApplySite applySite (memInst);
459
- return applySite.getArgumentOperandConvention (*memOper).isOwnedConvention ();
460
- }
461
- case SILInstructionKind::PartialApplyInst: {
462
- // If we are on the stack or have an inout convention, we do not
463
- // consume. Otherwise, we do.
464
- auto *pai = cast<PartialApplyInst>(memInst);
465
- if (pai->isOnStack ())
466
- return false ;
467
- ApplySite applySite (pai);
468
- auto convention = applySite.getArgumentConvention (*memOper);
469
- return !convention.isInoutConvention ();
343
+ auto *cai = cast<CopyAddrInst>(memInst);
344
+ return !cai->isInitializationOfDest ();
345
+ }
346
+ case SILInstructionKind::StoreInst: {
347
+ auto *si = cast<StoreInst>(memInst);
348
+ return si->getOwnershipQualifier () == StoreOwnershipQualifier::Assign;
470
349
}
471
- case SILInstructionKind::DestroyAddrInst:
472
- return true ;
473
- case SILInstructionKind::LoadInst:
474
- return cast<LoadInst>(memInst)->getOwnershipQualifier () ==
475
- LoadOwnershipQualifier::Take;
476
350
}
477
351
}
478
352
@@ -1725,7 +1599,7 @@ bool GatherUsesVisitor::visitUse(Operand *op) {
1725
1599
LLVM_DEBUG (llvm::dbgs () << " Visiting user: " << *user;);
1726
1600
1727
1601
// First check if we have init/reinit. These are quick/simple.
1728
- if (::memInstMustInitialize (op)) {
1602
+ if (noncopyable ::memInstMustInitialize (op)) {
1729
1603
LLVM_DEBUG (llvm::dbgs () << " Found init: " << *user);
1730
1604
1731
1605
// TODO: What about copy_addr of itself. We really should just pre-process
@@ -1739,7 +1613,7 @@ bool GatherUsesVisitor::visitUse(Operand *op) {
1739
1613
return true ;
1740
1614
}
1741
1615
1742
- if (::memInstMustReinitialize (op)) {
1616
+ if (noncopyable ::memInstMustReinitialize (op)) {
1743
1617
LLVM_DEBUG (llvm::dbgs () << " Found reinit: " << *user);
1744
1618
assert (!useState.reinitInsts .count (user));
1745
1619
auto leafRange = TypeTreeLeafTypeRange::get (op->get (), getRootAddress ());
@@ -2024,7 +1898,7 @@ bool GatherUsesVisitor::visitUse(Operand *op) {
2024
1898
2025
1899
// Now that we have handled or loadTakeOrCopy, we need to now track our
2026
1900
// additional pure takes.
2027
- if (::memInstMustConsume (op)) {
1901
+ if (noncopyable ::memInstMustConsume (op)) {
2028
1902
// If we don't have a consumeable and assignable check kind, then we can't
2029
1903
// consume. Emit an error.
2030
1904
//
@@ -3188,6 +3062,24 @@ bool MoveOnlyAddressCheckerPImpl::performSingleCheck(
3188
3062
state.process ();
3189
3063
}
3190
3064
3065
+ // Then if we have a let allocation, see if we have any copy_addr on our
3066
+ // markedAddress that form temporary allocation chains. This occurs when we
3067
+ // emit SIL for code like:
3068
+ //
3069
+ // let x: AddressOnlyType = ...
3070
+ // let _ = x.y.z
3071
+ //
3072
+ // SILGen will treat y as a separate rvalue from x and will create a temporary
3073
+ // allocation. In contrast if we have a var, we treat x like an lvalue and
3074
+ // just create GEPs appropriately.
3075
+ if (eliminateTemporaryAllocationsFromLet (markedAddress)) {
3076
+ LLVM_DEBUG (
3077
+ llvm::dbgs ()
3078
+ << " Succeeded in eliminating temporary allocations! Fn after:\n " ;
3079
+ markedAddress->getFunction ()->dump ());
3080
+ changed = true ;
3081
+ }
3082
+
3191
3083
// Then gather all uses of our address by walking from def->uses. We use this
3192
3084
// to categorize the uses of this address into their ownership behavior (e.g.:
3193
3085
// init, reinit, take, destroy, etc.).
0 commit comments