@@ -759,12 +759,13 @@ SILInstruction *SILCombiner::optimizeLoadFromStringLiteral(LoadInst *LI) {
759
759
760
760
// / Returns true if \p LI loads a zero integer from the empty Array, Dictionary
761
761
// / or Set singleton.
762
- static bool isZeroLoadFromEmptyCollection (LoadInst *LI) {
762
+ static bool isZeroLoadFromEmptyCollection (SingleValueInstruction *LI) {
763
+ assert (isa<LoadInst>(LI) || isa<LoadBorrowInst>(LI));
763
764
auto intTy = LI->getType ().getAs <BuiltinIntegerType>();
764
765
if (!intTy)
765
766
return false ;
766
-
767
- SILValue addr = LI->getOperand ();
767
+
768
+ SILValue addr = LI->getOperand (0 );
768
769
769
770
// Find the root object of the load-address.
770
771
for (;;) {
@@ -805,6 +806,8 @@ static bool isZeroLoadFromEmptyCollection(LoadInst *LI) {
805
806
case ValueKind::UpcastInst:
806
807
case ValueKind::RawPointerToRefInst:
807
808
case ValueKind::AddressToPointerInst:
809
+ case ValueKind::BeginBorrowInst:
810
+ case ValueKind::CopyValueInst:
808
811
case ValueKind::EndCOWMutationInst:
809
812
addr = cast<SingleValueInstruction>(addr)->getOperand (0 );
810
813
break ;
@@ -839,15 +842,56 @@ static SingleValueInstruction *getValueFromStaticLet(SILValue v) {
839
842
return nullptr ;
840
843
}
841
844
842
- SILInstruction *SILCombiner::visitLoadInst (LoadInst *LI) {
843
- if (LI->getFunction ()->hasOwnership ())
845
+ SILInstruction *SILCombiner::visitLoadBorrowInst (LoadBorrowInst *lbi) {
846
+ // (load (upcast-ptr %x)) -> (upcast-ref (load %x))
847
+ Builder.setCurrentDebugScope (lbi->getDebugScope ());
848
+ if (auto *ui = dyn_cast<UpcastInst>(lbi->getOperand ())) {
849
+ // We want to RAUW the current load_borrow with the upcast. To do that
850
+ // safely, we need to insert new end_borrow on the new load_borrow, erase
851
+ // the end_borrow and then RAUW.
852
+ SmallVector<EndBorrowInst *, 32 > endBorrowInst;
853
+ for (auto *ebi : lbi->getEndBorrows ())
854
+ endBorrowInst.push_back (ebi);
855
+ auto newLBI = Builder.createLoadBorrow (lbi->getLoc (), ui->getOperand ());
856
+ for (auto *ebi : endBorrowInst) {
857
+ SILBuilderWithScope builder (ebi, Builder);
858
+ builder.emitEndBorrowOperation (ebi->getLoc (), newLBI);
859
+ eraseInstFromFunction (*ebi);
860
+ }
861
+ auto *uci = Builder.createUpcast (lbi->getLoc (), newLBI, lbi->getType ());
862
+ replaceInstUsesWith (*lbi, uci);
863
+ return eraseInstFromFunction (*lbi);
864
+ }
865
+
866
+ // Constant-propagate the 0 value when loading "count" or "capacity" from the
867
+ // empty Array, Set or Dictionary storage.
868
+ // On high-level SIL this optimization is also done by the
869
+ // ArrayCountPropagation pass, but only for Array. And even for Array it's
870
+ // sometimes needed to propagate the empty-array count when high-level
871
+ // semantics function are already inlined.
872
+ // Note that for non-empty arrays/sets/dictionaries, the count can be
873
+ // propagated by redundant load elimination.
874
+ if (isZeroLoadFromEmptyCollection (lbi))
875
+ return Builder.createIntegerLiteral (lbi->getLoc (), lbi->getType (), 0 );
876
+
877
+ // If we have a load_borrow that only has non_debug end_borrow uses, delete
878
+ // it.
879
+ if (llvm::all_of (getNonDebugUses (lbi), [](Operand *use) {
880
+ return isa<EndBorrowInst>(use->getUser ());
881
+ })) {
882
+ eraseInstIncludingUsers (lbi);
844
883
return nullptr ;
884
+ }
885
+
886
+ return nullptr ;
887
+ }
845
888
889
+ SILInstruction *SILCombiner::visitLoadInst (LoadInst *LI) {
846
890
// (load (upcast-ptr %x)) -> (upcast-ref (load %x))
847
891
Builder.setCurrentDebugScope (LI->getDebugScope ());
848
892
if (auto *UI = dyn_cast<UpcastInst>(LI->getOperand ())) {
849
- auto NewLI = Builder.createLoad (LI->getLoc (), UI->getOperand (),
850
- LoadOwnershipQualifier::Unqualified );
893
+ auto NewLI = Builder.emitLoadValueOperation (LI->getLoc (), UI->getOperand (),
894
+ LI-> getOwnershipQualifier () );
851
895
return Builder.createUpcast (LI->getLoc (), NewLI, LI->getType ());
852
896
}
853
897
@@ -874,6 +918,17 @@ SILInstruction *SILCombiner::visitLoadInst(LoadInst *LI) {
874
918
return cloner.clone (initVal);
875
919
}
876
920
921
+ // If we have a load [copy] whose only non-debug users are destroy_value, just
922
+ // eliminate it.
923
+ if (LI->getOwnershipQualifier () == LoadOwnershipQualifier::Copy) {
924
+ if (llvm::all_of (getNonDebugUses (LI), [](Operand *use) {
925
+ return isa<DestroyValueInst>(use->getUser ());
926
+ })) {
927
+ eraseInstIncludingUsers (LI);
928
+ return nullptr ;
929
+ }
930
+ }
931
+
877
932
return nullptr ;
878
933
}
879
934
0 commit comments