@@ -36,25 +36,6 @@ STATISTIC(NumEliminatedInsts, "number of removed instructions");
36
36
STATISTIC (NumLoadCopyConvertedToLoadBorrow,
37
37
" number of load_copy converted to load_borrow" );
38
38
39
- // ===----------------------------------------------------------------------===//
40
- // Utility
41
- // ===----------------------------------------------------------------------===//
42
-
43
- static bool isConsumingOwnedUse (Operand *use) {
44
- assert (use->get ().getOwnershipKind () == ValueOwnershipKind::Owned);
45
-
46
- if (use->isTypeDependent ())
47
- return false ;
48
-
49
- // We know that a copy_value produces an @owned value. Look through all of
50
- // our uses and classify them as either invalidating or not
51
- // invalidating. Make sure that all of the invalidating ones are
52
- // destroy_value since otherwise the live_range is not complete.
53
- auto map = use->getOwnershipKindMap ();
54
- auto constraint = map.getLifetimeConstraint (ValueOwnershipKind::Owned);
55
- return constraint == UseLifetimeConstraint::MustBeInvalidated;
56
- }
57
-
58
39
// ===----------------------------------------------------------------------===//
59
40
// Live Range Modeling
60
41
// ===----------------------------------------------------------------------===//
@@ -325,7 +306,7 @@ struct SemanticARCOptVisitor
325
306
FORWARDING_TERM (CondBranch)
326
307
#undef FORWARDING_TERM
327
308
328
- bool isWrittenTo (LoadInst *li, ArrayRef<SILInstruction *> destroys );
309
+ bool isWrittenTo (LoadInst *li, const LiveRange &lr );
329
310
330
311
bool processWorklist ();
331
312
@@ -695,22 +676,20 @@ class StorageGuaranteesLoadVisitor
695
676
{
696
677
// The outer SemanticARCOptVisitor.
697
678
SemanticARCOptVisitor &ARCOpt;
698
-
699
- // The original load instruction .
700
- LoadInst *Load ;
701
-
679
+
680
+ // The live range of the original load.
681
+ const LiveRange &liveRange ;
682
+
702
683
// The current address being visited.
703
684
SILValue currentAddress;
704
685
705
686
Optional<bool > isWritten;
706
687
707
- ArrayRef<SILInstruction *> destroyValues;
708
-
709
688
public:
710
689
StorageGuaranteesLoadVisitor (SemanticARCOptVisitor &arcOpt, LoadInst *load,
711
- ArrayRef<SILInstruction *> destroyValues )
712
- : ARCOpt(arcOpt), Load(load), currentAddress(load-> getOperand () ),
713
- destroyValues(destroyValues ) {}
690
+ const LiveRange &liveRange )
691
+ : ARCOpt(arcOpt), liveRange(liveRange ),
692
+ currentAddress (load-> getOperand () ) {}
714
693
715
694
void answer (bool written) {
716
695
currentAddress = nullptr ;
@@ -793,28 +772,11 @@ class StorageGuaranteesLoadVisitor
793
772
llvm::copy (borrowInst->getUsersOfType <EndBorrowInst>(),
794
773
std::back_inserter (baseEndBorrows));
795
774
796
- SmallVector<SILInstruction *, 4 > valueDestroys;
797
- for (auto *use : Load->getUses ()) {
798
- // If this load is not consuming, skip it.
799
- if (!isConsumingOwnedUse (use)) {
800
- continue ;
801
- }
802
-
803
- // Otherwise, if this isn't a destroy_value, we have a consuming use we
804
- // don't understand. Return conservatively that this memory location may
805
- // not be guaranteed.
806
- auto *user = use->getUser ();
807
- if (!isa<DestroyValueInst>(user)) {
808
- return answer (true );
809
- }
810
- valueDestroys.emplace_back (user);
811
- }
812
-
813
775
SmallPtrSet<SILBasicBlock *, 4 > visitedBlocks;
814
776
LinearLifetimeChecker checker (visitedBlocks, ARCOpt.getDeadEndBlocks ());
815
777
// Returns true on success. So we invert.
816
- bool foundError =
817
- !checker. validateLifetime (baseObject, baseEndBorrows, valueDestroys );
778
+ bool foundError = !checker. validateLifetime (baseObject, baseEndBorrows,
779
+ liveRange. getDestroys () );
818
780
return answer (foundError);
819
781
}
820
782
@@ -850,9 +812,9 @@ class StorageGuaranteesLoadVisitor
850
812
SmallPtrSet<SILBasicBlock *, 4 > visitedBlocks;
851
813
LinearLifetimeChecker checker (visitedBlocks, ARCOpt.getDeadEndBlocks ());
852
814
// Returns true on success. So we invert.
853
- bool foundError =
854
- !checker. validateLifetime ( stack, destroyAddrs /* consuming users*/ ,
855
- destroyValues /* non consuming users*/ );
815
+ bool foundError = !checker. validateLifetime (
816
+ stack, destroyAddrs /* consuming users*/ ,
817
+ liveRange. getDestroys () /* non consuming users*/ );
856
818
return answer (foundError);
857
819
}
858
820
@@ -866,9 +828,8 @@ class StorageGuaranteesLoadVisitor
866
828
867
829
} // namespace
868
830
869
- bool SemanticARCOptVisitor::isWrittenTo (LoadInst *load,
870
- ArrayRef<SILInstruction *> destroys) {
871
- StorageGuaranteesLoadVisitor visitor (*this , load, destroys);
831
+ bool SemanticARCOptVisitor::isWrittenTo (LoadInst *load, const LiveRange &lr) {
832
+ StorageGuaranteesLoadVisitor visitor (*this , load, lr);
872
833
return visitor.doIt ();
873
834
}
874
835
@@ -892,8 +853,7 @@ bool SemanticARCOptVisitor::visitLoadInst(LoadInst *li) {
892
853
// Then check if our address is ever written to. If it is, then we cannot use
893
854
// the load_borrow because the stored value may be released during the loaded
894
855
// value's live range.
895
- auto destroyValues = lr.getDestroys ();
896
- if (isWrittenTo (li, destroyValues))
856
+ if (isWrittenTo (li, lr))
897
857
return false ;
898
858
899
859
// Ok, we can perform our optimization. Convert the load [copy] into a
@@ -906,6 +866,7 @@ bool SemanticARCOptVisitor::visitLoadInst(LoadInst *li) {
906
866
// to find the post-dominating block set of these destroy value to ensure that
907
867
// we do not insert multiple end_borrow.
908
868
assert (lifetimeFrontier.empty ());
869
+ auto destroyValues = lr.getDestroys ();
909
870
ValueLifetimeAnalysis analysis (li, destroyValues);
910
871
bool foundCriticalEdges = !analysis.computeFrontier (
911
872
lifetimeFrontier, ValueLifetimeAnalysis::DontModifyCFG,
0 commit comments