@@ -247,36 +247,46 @@ namespace {
247
247
248
248
// / This is the main entry point for the use walker. It collects uses from
249
249
// / the address and the refcount result of the allocation.
250
- void collectFrom () {
251
- if (auto *ABI = TheMemory.getContainer ())
252
- collectContainerUses (ABI);
253
- else
254
- collectUses (TheMemory.getAddress (), 0 );
255
-
256
- // Collect information about the retain count result as well.
257
- for (auto UI : TheMemory.MemoryInst ->getUses ()) {
258
- auto *User = UI->getUser ();
259
-
260
- // If this is a release or dealloc_stack, then remember it as such.
261
- if (isa<StrongReleaseInst>(User) || isa<DeallocStackInst>(User) ||
262
- isa<DeallocBoxInst>(User)) {
263
- Releases.push_back (User);
264
- }
265
- }
266
- }
250
+ LLVM_NODISCARD bool collectFrom ();
267
251
268
252
private:
269
- void collectUses (SILValue Pointer, unsigned BaseEltNo);
270
- void collectContainerUses (AllocBoxInst *ABI);
253
+ LLVM_NODISCARD bool collectUses (SILValue Pointer, unsigned BaseEltNo);
254
+ LLVM_NODISCARD bool collectContainerUses (AllocBoxInst *ABI);
271
255
void addElementUses (unsigned BaseEltNo, SILType UseTy,
272
256
SILInstruction *User, DIUseKind Kind);
273
- void collectTupleElementUses (TupleElementAddrInst *TEAI,
274
- unsigned BaseEltNo);
275
- void collectStructElementUses (StructElementAddrInst *SEAI,
276
- unsigned BaseEltNo);
257
+ LLVM_NODISCARD bool collectTupleElementUses (TupleElementAddrInst *TEAI,
258
+ unsigned BaseEltNo);
259
+ LLVM_NODISCARD bool collectStructElementUses (StructElementAddrInst *SEAI,
260
+ unsigned BaseEltNo);
277
261
};
278
262
} // end anonymous namespace
279
263
264
+ bool ElementUseCollector::collectFrom () {
265
+ bool shouldOptimize = false ;
266
+
267
+ if (auto *ABI = TheMemory.getContainer ()) {
268
+ shouldOptimize = collectContainerUses (ABI);
269
+ } else {
270
+ shouldOptimize = collectUses (TheMemory.getAddress (), 0 );
271
+ }
272
+
273
+ if (!shouldOptimize)
274
+ return false ;
275
+
276
+ // Collect information about the retain count result as well.
277
+ for (auto UI : TheMemory.MemoryInst ->getUses ()) {
278
+ auto *User = UI->getUser ();
279
+
280
+ // If this is a release or dealloc_stack, then remember it as such.
281
+ if (isa<StrongReleaseInst>(User) || isa<DeallocStackInst>(User) ||
282
+ isa<DeallocBoxInst>(User)) {
283
+ Releases.push_back (User);
284
+ }
285
+ }
286
+
287
+ return true ;
288
+ }
289
+
280
290
// / addElementUses - An operation (e.g. load, store, inout use, etc) on a value
281
291
// / acts on all of the aggregate elements in that value. For example, a load
282
292
// / of $*(Int,Int) is a use of both Int elements of the tuple. This is a helper
@@ -295,8 +305,8 @@ void ElementUseCollector::addElementUses(unsigned BaseEltNo, SILType UseTy,
295
305
// / Given a tuple_element_addr or struct_element_addr, compute the new
296
306
// / BaseEltNo implicit in the selected member, and recursively add uses of
297
307
// / the instruction.
298
- void ElementUseCollector::
299
- collectTupleElementUses (TupleElementAddrInst *TEAI, unsigned BaseEltNo) {
308
+ bool ElementUseCollector::collectTupleElementUses (TupleElementAddrInst *TEAI,
309
+ unsigned BaseEltNo) {
300
310
301
311
// If we're walking into a tuple within a struct or enum, don't adjust the
302
312
// BaseElt. The uses hanging off the tuple_element_addr are going to be
@@ -314,20 +324,20 @@ collectTupleElementUses(TupleElementAddrInst *TEAI, unsigned BaseEltNo) {
314
324
BaseEltNo += getElementCountRec (Module, EltTy);
315
325
}
316
326
}
317
-
318
- collectUses (TEAI, BaseEltNo);
327
+
328
+ return collectUses (TEAI, BaseEltNo);
319
329
}
320
330
321
- void ElementUseCollector::collectStructElementUses (StructElementAddrInst *SEAI,
331
+ bool ElementUseCollector::collectStructElementUses (StructElementAddrInst *SEAI,
322
332
unsigned BaseEltNo) {
323
333
// Generally, we set the "InStructSubElement" flag and recursively process
324
334
// the uses so that we know that we're looking at something within the
325
335
// current element.
326
336
llvm::SaveAndRestore<bool > X (InStructSubElement, true );
327
- collectUses (SEAI, BaseEltNo);
337
+ return collectUses (SEAI, BaseEltNo);
328
338
}
329
339
330
- void ElementUseCollector::collectContainerUses (AllocBoxInst *ABI) {
340
+ bool ElementUseCollector::collectContainerUses (AllocBoxInst *ABI) {
331
341
for (Operand *UI : ABI->getUses ()) {
332
342
auto *User = UI->getUser ();
333
343
@@ -340,16 +350,21 @@ void ElementUseCollector::collectContainerUses(AllocBoxInst *ABI) {
340
350
continue ;
341
351
342
352
if (auto project = dyn_cast<ProjectBoxInst>(User)) {
343
- collectUses (project, project->getFieldIndex ());
353
+ if (!collectUses (project, project->getFieldIndex ()))
354
+ return false ;
344
355
continue ;
345
356
}
346
357
347
358
// Other uses of the container are considered escapes of the values.
348
- for (unsigned field : indices (ABI->getBoxType ()->getLayout ()->getFields ()))
359
+ for (unsigned field :
360
+ indices (ABI->getBoxType ()->getLayout ()->getFields ())) {
349
361
addElementUses (field,
350
362
ABI->getBoxType ()->getFieldType (ABI->getModule (), field),
351
363
User, DIUseKind::Escape);
364
+ }
352
365
}
366
+
367
+ return true ;
353
368
}
354
369
355
370
// Returns true when the instruction represents added instrumentation for
@@ -367,7 +382,7 @@ static bool isSanitizerInstrumentation(SILInstruction *Instruction,
367
382
return false ;
368
383
}
369
384
370
- void ElementUseCollector::collectUses (SILValue Pointer, unsigned BaseEltNo) {
385
+ bool ElementUseCollector::collectUses (SILValue Pointer, unsigned BaseEltNo) {
371
386
assert (Pointer->getType ().isAddress () &&
372
387
" Walked through the pointer to the value?" );
373
388
SILType PointeeType = Pointer->getType ().getObjectType ();
@@ -383,19 +398,22 @@ void ElementUseCollector::collectUses(SILValue Pointer, unsigned BaseEltNo) {
383
398
384
399
// struct_element_addr P, #field indexes into the current element.
385
400
if (auto *SEAI = dyn_cast<StructElementAddrInst>(User)) {
386
- collectStructElementUses (SEAI, BaseEltNo);
401
+ if (!collectStructElementUses (SEAI, BaseEltNo))
402
+ return false ;
387
403
continue ;
388
404
}
389
405
390
406
// Instructions that compute a subelement are handled by a helper.
391
407
if (auto *TEAI = dyn_cast<TupleElementAddrInst>(User)) {
392
- collectTupleElementUses (TEAI, BaseEltNo);
408
+ if (!collectTupleElementUses (TEAI, BaseEltNo))
409
+ return false ;
393
410
continue ;
394
411
}
395
412
396
413
// Look through begin_access.
397
414
if (auto I = dyn_cast<BeginAccessInst>(User)) {
398
- collectUses (I, BaseEltNo);
415
+ if (!collectUses (I, BaseEltNo))
416
+ return false ;
399
417
continue ;
400
418
}
401
419
@@ -439,7 +457,7 @@ void ElementUseCollector::collectUses(SILValue Pointer, unsigned BaseEltNo) {
439
457
continue ;
440
458
}
441
459
442
- if (auto *SWI = dyn_cast<StoreWeakInst>(User))
460
+ if (auto *SWI = dyn_cast<StoreWeakInst>(User)) {
443
461
if (UI->getOperandNumber () == 1 ) {
444
462
DIUseKind Kind;
445
463
if (InStructSubElement)
@@ -451,8 +469,9 @@ void ElementUseCollector::collectUses(SILValue Pointer, unsigned BaseEltNo) {
451
469
Uses.push_back (DIMemoryUse (User, Kind, BaseEltNo, 1 ));
452
470
continue ;
453
471
}
472
+ }
454
473
455
- if (auto *SUI = dyn_cast<StoreUnownedInst>(User))
474
+ if (auto *SUI = dyn_cast<StoreUnownedInst>(User)) {
456
475
if (UI->getOperandNumber () == 1 ) {
457
476
DIUseKind Kind;
458
477
if (InStructSubElement)
@@ -464,6 +483,7 @@ void ElementUseCollector::collectUses(SILValue Pointer, unsigned BaseEltNo) {
464
483
Uses.push_back (DIMemoryUse (User, Kind, BaseEltNo, 1 ));
465
484
continue ;
466
485
}
486
+ }
467
487
468
488
if (auto *CAI = dyn_cast<CopyAddrInst>(User)) {
469
489
// If this is a copy of a tuple, we should scalarize it so that we don't
@@ -505,7 +525,13 @@ void ElementUseCollector::collectUses(SILValue Pointer, unsigned BaseEltNo) {
505
525
// If this is an out-parameter, it is like a store.
506
526
unsigned NumIndirectResults = substConv.getNumIndirectSILResults ();
507
527
if (ArgumentNumber < NumIndirectResults) {
508
- assert (!InStructSubElement && " We're initializing sub-members?" );
528
+ // We do not support initializing sub members. This is an old
529
+ // restriction from when this code was used by Definite
530
+ // Initialization. With proper code review, we can remove this, but for
531
+ // now, lets be conservative.
532
+ if (InStructSubElement) {
533
+ return false ;
534
+ }
509
535
addElementUses (BaseEltNo, PointeeType, User,
510
536
DIUseKind::Initialization);
511
537
continue ;
@@ -550,29 +576,38 @@ void ElementUseCollector::collectUses(SILValue Pointer, unsigned BaseEltNo) {
550
576
// be explicitly initialized by a copy_addr or some other use of the
551
577
// projected address).
552
578
if (auto I = dyn_cast<InitEnumDataAddrInst>(User)) {
553
- assert (!InStructSubElement &&
554
- " init_enum_data_addr shouldn't apply to struct subelements" );
579
+ // If we are in a struct already, bail. With proper analysis, we should be
580
+ // able to do this optimization.
581
+ if (InStructSubElement) {
582
+ return false ;
583
+ }
584
+
555
585
// Keep track of the fact that we're inside of an enum. This informs our
556
586
// recursion that tuple stores are not scalarized outside, and that stores
557
587
// should not be treated as partial stores.
558
588
llvm::SaveAndRestore<bool > X (InEnumSubElement, true );
559
- collectUses (I, BaseEltNo);
589
+ if (!collectUses (I, BaseEltNo))
590
+ return false ;
560
591
continue ;
561
592
}
562
593
563
594
// init_existential_addr is modeled as an initialization store.
564
595
if (isa<InitExistentialAddrInst>(User)) {
565
- assert (!InStructSubElement &&
566
- " init_existential_addr should not apply to struct subelements" );
596
+ // init_existential_addr should not apply to struct subelements.
597
+ if (InStructSubElement) {
598
+ return false ;
599
+ }
567
600
Uses.push_back (DIMemoryUse (User, DIUseKind::Initialization,
568
601
BaseEltNo, 1 ));
569
602
continue ;
570
603
}
571
604
572
605
// inject_enum_addr is modeled as an initialization store.
573
606
if (isa<InjectEnumAddrInst>(User)) {
574
- assert (!InStructSubElement &&
575
- " inject_enum_addr the subelement of a struct unless in a ctor" );
607
+ // inject_enum_addr the subelement of a struct unless in a ctor.
608
+ if (InStructSubElement) {
609
+ return false ;
610
+ }
576
611
Uses.push_back (DIMemoryUse (User, DIUseKind::Initialization,
577
612
BaseEltNo, 1 ));
578
613
continue ;
@@ -667,16 +702,22 @@ void ElementUseCollector::collectUses(SILValue Pointer, unsigned BaseEltNo) {
667
702
// Now that we've scalarized some stuff, recurse down into the newly created
668
703
// element address computations to recursively process it. This can cause
669
704
// further scalarization.
670
- for (auto EltPtr : ElementAddrs)
671
- collectTupleElementUses (cast<TupleElementAddrInst>(EltPtr), BaseEltNo);
705
+ if (llvm::any_of (ElementAddrs, [&](SILValue V) {
706
+ return !collectTupleElementUses (cast<TupleElementAddrInst>(V),
707
+ BaseEltNo);
708
+ })) {
709
+ return false ;
710
+ }
672
711
}
712
+
713
+ return true ;
673
714
}
674
715
675
716
// / collectDIElementUsesFrom - Analyze all uses of the specified allocation
676
717
// / instruction (alloc_box, alloc_stack or mark_uninitialized), classifying them
677
718
// / and storing the information found into the Uses and Releases lists.
678
- void swift::collectDIElementUsesFrom (
719
+ bool swift::collectDIElementUsesFrom (
679
720
const DIMemoryObjectInfo &MemoryInfo, SmallVectorImpl<DIMemoryUse> &Uses,
680
721
SmallVectorImpl<SILInstruction *> &Releases) {
681
- ElementUseCollector (MemoryInfo, Uses, Releases).collectFrom ();
722
+ return ElementUseCollector (MemoryInfo, Uses, Releases).collectFrom ();
682
723
}
0 commit comments