@@ -783,10 +783,10 @@ bool SILCombiner::canReplaceArg(FullApplySite Apply,
783
783
// / (@in or @owned convention).
784
784
struct ConcreteArgumentCopy {
785
785
SILValue origArg;
786
- CopyAddrInst *tempArgCopy ;
786
+ AllocStackInst *tempArg ;
787
787
788
- ConcreteArgumentCopy (SILValue origArg, CopyAddrInst *tempArgCopy )
789
- : origArg(origArg), tempArgCopy(tempArgCopy ) {
788
+ ConcreteArgumentCopy (SILValue origArg, AllocStackInst *tempArg )
789
+ : origArg(origArg), tempArg(tempArg ) {
790
790
assert (origArg->getType ().isAddress ());
791
791
}
792
792
@@ -825,9 +825,18 @@ struct ConcreteArgumentCopy {
825
825
SILBuilderWithScope B (apply.getInstruction (), BuilderCtx);
826
826
auto loc = apply.getLoc ();
827
827
auto *ASI = B.createAllocStack (loc, CEI.ConcreteValue ->getType ());
828
- auto *CAI = B.createCopyAddr (loc, CEI.ConcreteValue , ASI, IsNotTake,
829
- IsInitialization_t::IsInitialization);
830
- return ConcreteArgumentCopy (origArg, CAI);
828
+ // If the type is an address, simple copy it.
829
+ if (CEI.ConcreteValue ->getType ().isAddress ()) {
830
+ B.createCopyAddr (loc, CEI.ConcreteValue , ASI, IsNotTake,
831
+ IsInitialization_t::IsInitialization);
832
+ } else {
833
+ // Otherwise, we probably got the value from the source of a store
834
+ // instruction so, create a store into the temporary argument.
835
+ B.createStrongRetain (loc, CEI.ConcreteValue , B.getDefaultAtomicity ());
836
+ B.createStore (loc, CEI.ConcreteValue , ASI,
837
+ StoreOwnershipQualifier::Unqualified);
838
+ }
839
+ return ConcreteArgumentCopy (origArg, ASI);
831
840
}
832
841
};
833
842
@@ -858,20 +867,19 @@ SILInstruction *SILCombiner::createApplyWithConcreteType(
858
867
FullApplySite Apply,
859
868
const llvm::SmallDenseMap<unsigned , ConcreteOpenedExistentialInfo> &COAIs,
860
869
SILBuilderContext &BuilderCtx) {
861
-
862
870
// Ensure that the callee is polymorphic.
863
871
assert (Apply.getOrigCalleeType ()->isPolymorphic ());
864
872
865
873
// Create the new set of arguments to apply including their substitutions.
866
874
SubstitutionMap NewCallSubs = Apply.getSubstitutionMap ();
867
875
SmallVector<SILValue, 8 > NewArgs;
868
- bool UpdatedArgs = false ;
869
876
unsigned ArgIdx = 0 ;
870
877
// Push the indirect result arguments.
871
878
for (unsigned EndIdx = Apply.getSubstCalleeConv ().getSILArgIndexOfFirstParam ();
872
879
ArgIdx < EndIdx; ++ArgIdx) {
873
880
NewArgs.push_back (Apply.getArgument (ArgIdx));
874
881
}
882
+
875
883
// Transform the parameter arguments.
876
884
SmallVector<ConcreteArgumentCopy, 4 > concreteArgCopies;
877
885
for (unsigned EndIdx = Apply.getNumArguments (); ArgIdx < EndIdx; ++ArgIdx) {
@@ -890,16 +898,18 @@ SILInstruction *SILCombiner::createApplyWithConcreteType(
890
898
NewArgs.push_back (Apply.getArgument (ArgIdx));
891
899
continue ;
892
900
}
893
- UpdatedArgs = true ;
901
+
894
902
// Ensure that we have a concrete value to propagate.
895
903
assert (CEI.ConcreteValue );
904
+
896
905
auto argSub =
897
906
ConcreteArgumentCopy::generate (CEI, Apply, ArgIdx, BuilderCtx);
898
907
if (argSub) {
899
908
concreteArgCopies.push_back (*argSub);
900
- NewArgs.push_back (argSub->tempArgCopy -> getDest () );
901
- } else
909
+ NewArgs.push_back (argSub->tempArg );
910
+ } else {
902
911
NewArgs.push_back (CEI.ConcreteValue );
912
+ }
903
913
904
914
// Form a new set of substitutions where the argument is
905
915
// replaced with a concrete type.
@@ -922,7 +932,33 @@ SILInstruction *SILCombiner::createApplyWithConcreteType(
922
932
});
923
933
}
924
934
925
- if (!UpdatedArgs) {
935
+ // We need to make sure that we can a) update Apply to use the new args and b)
936
+ // at least one argument has changed. If no arguments have changed, we need
937
+ // to return nullptr. Otherwise, we will have an infinite loop.
938
+ auto substTy =
939
+ Apply.getCallee ()
940
+ ->getType ()
941
+ .substGenericArgs (Apply.getModule (), NewCallSubs,
942
+ Apply.getFunction ()->getTypeExpansionContext ())
943
+ .getAs <SILFunctionType>();
944
+ SILFunctionConventions conv (substTy,
945
+ SILModuleConventions (Apply.getModule ()));
946
+ bool canUpdateArgs = true ;
947
+ bool madeUpdate = false ;
948
+ for (unsigned index = 0 ; index < conv.getNumSILArguments (); ++index) {
949
+ // Make sure that *all* the arguments in both the new substitution function
950
+ // and our vector of new arguments have the same type.
951
+ canUpdateArgs &=
952
+ conv.getSILArgumentType (index) == NewArgs[index]->getType ();
953
+ // Make sure that we have changed at least one argument.
954
+ madeUpdate |=
955
+ NewArgs[index]->getType () != Apply.getArgument (index)->getType ();
956
+ }
957
+
958
+ // If we can't update the args (because of a type mismatch) or the args don't
959
+ // change, bail out by removing the instructions we've added and returning
960
+ // nullptr.
961
+ if (!canUpdateArgs || !madeUpdate) {
926
962
// Remove any new instructions created while attempting to optimize this
927
963
// apply. Since the apply was never rewritten, if they aren't removed here,
928
964
// they will be removed later as dead when visited by SILCombine, causing
@@ -969,8 +1005,7 @@ SILInstruction *SILCombiner::createApplyWithConcreteType(
969
1005
auto cleanupLoc = RegularLocation::getAutoGeneratedLocation ();
970
1006
for (ConcreteArgumentCopy &argCopy : llvm::reverse (concreteArgCopies)) {
971
1007
cleanupBuilder.createDestroyAddr (cleanupLoc, argCopy.origArg );
972
- cleanupBuilder.createDeallocStack (cleanupLoc,
973
- argCopy.tempArgCopy ->getDest ());
1008
+ cleanupBuilder.createDeallocStack (cleanupLoc, argCopy.tempArg );
974
1009
}
975
1010
}
976
1011
return NewApply.getInstruction ();
0 commit comments