19
19
// ===----------------------------------------------------------------------===//
20
20
21
21
#define DEBUG_TYPE " let-properties-opt"
22
- #include " swift/SIL/SILInstruction.h"
23
- #include " swift/SIL/SILBasicBlock.h"
24
22
#include " swift/SIL/DebugUtils.h"
23
+ #include " swift/SIL/InstructionUtils.h"
24
+ #include " swift/SIL/SILBasicBlock.h"
25
+ #include " swift/SIL/SILInstruction.h"
25
26
#include " swift/SIL/SILLinkage.h"
26
27
#include " swift/SILOptimizer/PassManager/Passes.h"
27
28
#include " swift/SILOptimizer/PassManager/Transforms.h"
@@ -201,7 +202,10 @@ void LetPropertiesOpt::optimizeLetPropertyAccess(VarDecl *Property,
201
202
};
202
203
203
204
// Look for any instructions accessing let properties.
204
- if (auto proj = dyn_cast<RefElementAddrInst>(Load)) {
205
+ if (isa<RefElementAddrInst>(Load) || isa<StructElementAddrInst>(Load)
206
+ || isa<BeginAccessInst>(Load)) {
207
+ auto proj = cast<SingleValueInstruction>(Load);
208
+
205
209
// Copy the initializer into the function
206
210
// Replace the access to a let property by the value
207
211
// computed by this initializer.
@@ -210,6 +214,14 @@ void LetPropertiesOpt::optimizeLetPropertyAccess(VarDecl *Property,
210
214
for (auto UI = proj->use_begin (), E = proj->use_end (); UI != E;) {
211
215
auto *User = UI->getUser ();
212
216
++UI;
217
+
218
+ if (isIncidentalUse (User))
219
+ continue ;
220
+
221
+ // A nested begin_access will be mapped as a separate "Load".
222
+ if (isa<BeginAccessInst>(User))
223
+ continue ;
224
+
213
225
if (isa<StoreInst>(User))
214
226
continue ;
215
227
@@ -231,23 +243,6 @@ void LetPropertiesOpt::optimizeLetPropertyAccess(VarDecl *Property,
231
243
proj->eraseFromParent ();
232
244
++NumReplaced;
233
245
ChangedFunctions.insert (F);
234
- } else if (auto proj = dyn_cast<StructElementAddrInst>(Load)) {
235
- // Copy the initializer into the function
236
- // Replace the access to a let property by the value
237
- // computed by this initializer.
238
- SILValue clonedInit = cloneInitAt (proj);
239
- SILBuilderWithScope B (proj);
240
- for (auto UI = proj->use_begin (), E = proj->use_end (); UI != E;) {
241
- auto *User = UI->getUser ();
242
- ++UI;
243
- if (isa<StoreInst>(User))
244
- continue ;
245
- replaceLoadSequence (User, clonedInit, B);
246
- eraseUsesOfInstruction (User);
247
- User->eraseFromParent ();
248
- ++NumReplaced;
249
- }
250
- ChangedFunctions.insert (F);
251
246
}
252
247
}
253
248
@@ -422,7 +417,7 @@ LetPropertiesOpt::analyzeInitValue(SILInstruction *I, VarDecl *Property) {
422
417
if (auto SI = dyn_cast<StructInst>(I)) {
423
418
value = SI->getFieldValue (Property);
424
419
} else if (auto SI = dyn_cast<StoreInst>(I)) {
425
- auto Dest = SI->getDest ();
420
+ auto Dest = stripAddressAccess ( SI->getDest () );
426
421
427
422
assert (((isa<RefElementAddrInst>(Dest) &&
428
423
cast<RefElementAddrInst>(Dest)->getField () == Property) ||
@@ -524,9 +519,12 @@ static bool isValidPropertyLoad(SILInstruction *I) {
524
519
525
520
if (isa<StructElementAddrInst>(I) || isa<TupleElementAddrInst>(I)) {
526
521
auto projection = cast<SingleValueInstruction>(I);
527
- for (auto Use : getNonDebugUses (projection))
522
+ for (auto Use : getNonDebugUses (projection)) {
523
+ if (isIncidentalUse (Use->getUser ()))
524
+ continue ;
528
525
if (!isValidPropertyLoad (Use->getUser ()))
529
526
return false ;
527
+ }
530
528
return true ;
531
529
}
532
530
@@ -545,11 +543,19 @@ void LetPropertiesOpt::collectPropertyAccess(SILInstruction *I,
545
543
<< " ':\n " ;
546
544
llvm::dbgs () << " The instructions are:\n " ; I->dumpInContext ());
547
545
548
- if (isa<RefElementAddrInst>(I) || isa<StructElementAddrInst>(I)) {
546
+ if (isa<RefElementAddrInst>(I) || isa<StructElementAddrInst>(I)
547
+ || isa<BeginAccessInst>(I)) {
549
548
// Check if there is a store to this property.
550
549
auto projection = cast<SingleValueInstruction>(I);
551
550
for (auto Use : getNonDebugUses (projection)) {
552
551
auto *User = Use->getUser ();
552
+ if (isIncidentalUse (User))
553
+ continue ;
554
+
555
+ // Each begin_access is analyzed as a separate property access. Do not
556
+ // consider a begin_access a use of the current projection.
557
+ if (isa<BeginAccessInst>(User))
558
+ continue ;
553
559
554
560
if (auto *SI = dyn_cast<StoreInst>(User)) {
555
561
// There is a store into this property.
@@ -595,7 +601,12 @@ void LetPropertiesOpt::run(SILModuleTransform *T) {
595
601
// It includes referencing this specific property (both reads and
596
602
// stores), as well as implicit stores by means of e.g.
597
603
// a struct instruction.
598
- if (auto *REAI = dyn_cast<RefElementAddrInst>(&I)) {
604
+ if (auto *BAI = dyn_cast<BeginAccessInst>(&I)) {
605
+ if (auto *REAI =
606
+ dyn_cast<RefElementAddrInst>(stripAddressAccess (BAI))) {
607
+ collectPropertyAccess (BAI, REAI->getField (), NonRemovable);
608
+ }
609
+ } else if (auto *REAI = dyn_cast<RefElementAddrInst>(&I)) {
599
610
collectPropertyAccess (REAI, REAI->getField (), NonRemovable);
600
611
} else if (auto *SEI = dyn_cast<StructExtractInst>(&I)) {
601
612
collectPropertyAccess (SEI, SEI->getField (), NonRemovable);
0 commit comments