@@ -804,6 +804,18 @@ SILInstruction *SILCombiner::optimizeLoadFromStringLiteral(LoadInst *LI) {
804
804
return Builder.createIntegerLiteral (LI->getLoc (), LI->getType (), str[index]);
805
805
}
806
806
807
+ static bool isShiftRightByAtLeastOne (SILInstruction *inst) {
808
+ auto *bi = dyn_cast<BuiltinInst>(inst);
809
+ if (!bi)
810
+ return false ;
811
+ if (bi->getBuiltinInfo ().ID != BuiltinValueKind::LShr)
812
+ return false ;
813
+ auto *shiftVal = dyn_cast<IntegerLiteralInst>(bi->getArguments ()[1 ]);
814
+ if (!shiftVal)
815
+ return false ;
816
+ return shiftVal->getValue ().isStrictlyPositive ();
817
+ }
818
+
807
819
// / Returns true if \p LI loads a zero integer from the empty Array, Dictionary
808
820
// / or Set singleton.
809
821
static bool isZeroLoadFromEmptyCollection (SingleValueInstruction *LI) {
@@ -826,15 +838,23 @@ static bool isZeroLoadFromEmptyCollection(SingleValueInstruction *LI) {
826
838
}
827
839
case ValueKind::StructElementAddrInst: {
828
840
auto *SEA = cast<StructElementAddrInst>(addr);
829
- // For Array, we only support "count". The value of "capacityAndFlags"
830
- // is not defined in the ABI and could change in another version of the
831
- // runtime (the capacity must be 0, but the flags may be not 0).
832
- if (SEA->getStructDecl ()->getName ().is (" _SwiftArrayBodyStorage" ) &&
833
- !SEA->getField ()->getName ().is (" count" )) {
834
- return false ;
835
- }
836
841
addr = SEA->getOperand ();
837
- break ;
842
+ if (!SEA->getStructDecl ()->getName ().is (" _SwiftArrayBodyStorage" ))
843
+ break ;
844
+ if (SEA->getField ()->getName ().is (" count" ))
845
+ break ;
846
+ // For Array, the value of `capacityAndFlags` has only a zero capacity
847
+ // but not necessarily a zero flag (in fact, the flag is 1).
848
+ // Therefore only replace `capacityAndFlags` with zero if the flag is
849
+ // masked out by a right-shift of 1.
850
+ if (SEA->getField ()->getName ().is (" _capacityAndFlags" )) {
851
+ for (Operand *loadUse : LI->getUses ()) {
852
+ if (!isShiftRightByAtLeastOne (loadUse->getUser ()))
853
+ return false ;
854
+ }
855
+ break ;
856
+ }
857
+ return false ;
838
858
}
839
859
case ValueKind::RefElementAddrInst: {
840
860
auto *REA = cast<RefElementAddrInst>(addr);
@@ -858,6 +878,13 @@ static bool isZeroLoadFromEmptyCollection(SingleValueInstruction *LI) {
858
878
case ValueKind::EndCOWMutationInst:
859
879
addr = cast<SingleValueInstruction>(addr)->getOperand (0 );
860
880
break ;
881
+ case ValueKind::MultipleValueInstructionResult:
882
+ if (auto *bci = dyn_cast<BeginCOWMutationInst>(
883
+ addr->getDefiningInstruction ())) {
884
+ addr = bci->getOperand ();
885
+ break ;
886
+ }
887
+ return false ;
861
888
default :
862
889
return false ;
863
890
}
0 commit comments