@@ -441,6 +441,7 @@ class HoistDestroys {
441
441
SmallVectorImpl<LoadInst *> &loads,
442
442
SmallVectorImpl<CopyAddrInst *> &copies,
443
443
SmallPtrSetImpl<AccessPath::PathNode> &leaves,
444
+ SmallPtrSetImpl<AccessPath::PathNode> &trivialLeaves,
444
445
const AccessStorage &storage,
445
446
const DeinitBarriers &deinitBarriers);
446
447
@@ -568,6 +569,25 @@ bool HoistDestroys::foldBarrier(SILInstruction *barrier,
568
569
// destroy_addr in order for folding to occur.
569
570
llvm::SmallPtrSet<AccessPath::PathNode, 16 > leaves;
570
571
572
+ // The trivial storage leaves of the root storage. They needn't be destroyed
573
+ // in the sequence prior to the destroy_addr, but their uses may obstruct
574
+ // folding. For example, given an %object and %triv a trivial subobject
575
+ //
576
+ // load [copy] %object
577
+ // load [trivial] %triv
578
+ // destroy_addr %object
579
+ //
580
+ // it isn't legal to fold the destroy_addr into the load of %object like
581
+ //
582
+ // load [take] %object
583
+ // load [trivial] %triv
584
+ //
585
+ // because the memory location %triv is no longer valid. In general, it would
586
+ // be fine to support folding over accesses of trivial subobjects so long as
587
+ // they occur prior to the access to some nontrivial subobject that contains
588
+ // it.
589
+ SmallPtrSet<AccessPath::PathNode, 16 > trivialLeaves;
590
+
571
591
visitProductLeafAccessPathNodes (storageRoot, typeExpansionContext, module ,
572
592
[&](AccessPath::PathNode node, SILType ty) {
573
593
if (ty.isTrivial (*function))
@@ -577,8 +597,8 @@ bool HoistDestroys::foldBarrier(SILInstruction *barrier,
577
597
578
598
for (auto *instruction = barrier; instruction != nullptr ;
579
599
instruction = instruction->getPreviousInstruction ()) {
580
- if (checkFoldingBarrier (instruction, loads, copies, leaves, storage ,
581
- deinitBarriers))
600
+ if (checkFoldingBarrier (instruction, loads, copies, leaves, trivialLeaves ,
601
+ storage, deinitBarriers))
582
602
return false ;
583
603
584
604
// If we have load [copy]s or copy_addrs of projections out of the root
@@ -672,8 +692,9 @@ bool HoistDestroys::foldBarrier(SILInstruction *barrier,
672
692
bool HoistDestroys::checkFoldingBarrier (
673
693
SILInstruction *instruction, SmallVectorImpl<LoadInst *> &loads,
674
694
SmallVectorImpl<CopyAddrInst *> &copies,
675
- SmallPtrSetImpl<AccessPath::PathNode> &leaves, const AccessStorage &storage,
676
- const DeinitBarriers &deinitBarriers) {
695
+ SmallPtrSetImpl<AccessPath::PathNode> &leaves,
696
+ SmallPtrSetImpl<AccessPath::PathNode> &trivialLeaves,
697
+ const AccessStorage &storage, const DeinitBarriers &deinitBarriers) {
677
698
// The address of a projection out of the root storage which would be
678
699
// folded if folding is possible.
679
700
//
@@ -720,14 +741,18 @@ bool HoistDestroys::checkFoldingBarrier(
720
741
// Find its nontrivial product leaves and remove them from the set of
721
742
// leaves of the root storage which we're wating to see.
722
743
bool alreadySawLeaf = false ;
723
- visitProductLeafAccessPathNodes (address, typeExpansionContext, module ,
724
- [&](AccessPath::PathNode node, SILType ty) {
725
- if (ty.isTrivial (*function))
726
- return ;
727
- bool erased = leaves.erase (node);
728
- alreadySawLeaf =
729
- alreadySawLeaf || !erased;
730
- });
744
+ bool alreadySawTrivialSubleaf = false ;
745
+ visitProductLeafAccessPathNodes (
746
+ address, typeExpansionContext, module ,
747
+ [&](AccessPath::PathNode node, SILType ty) {
748
+ if (ty.isTrivial (*function)) {
749
+ bool inserted = !trivialLeaves.insert (node).second ;
750
+ alreadySawTrivialSubleaf = alreadySawTrivialSubleaf || inserted;
751
+ return ;
752
+ }
753
+ bool erased = leaves.erase (node);
754
+ alreadySawLeaf = alreadySawLeaf || !erased;
755
+ });
731
756
if (alreadySawLeaf) {
732
757
// We saw this non-trivial product leaf already. That means there are
733
758
// multiple load [copy]s or copy_addrs of at least one product leaf
@@ -736,6 +761,11 @@ bool HoistDestroys::checkFoldingBarrier(
736
761
// Give up on folding.
737
762
return true ;
738
763
}
764
+ if (alreadySawTrivialSubleaf) {
765
+ // We saw this trivial leaf already. That means there was some later
766
+ // load [copy] or copy_addr of it. Give up on folding.
767
+ return true ;
768
+ }
739
769
} else if (deinitBarriers.isBarrier (instruction)) {
740
770
// We didn't find an instruction that was both
741
771
// - relevant (i.e. a copy_addr or a load [take])
0 commit comments