@@ -908,6 +908,37 @@ static void markReabstractionPartialApplyAsUsed(
908
908
llvm_unreachable (" Unexpect instruction" );
909
909
}
910
910
911
+ // / Returns true if the \p closureArgIdx argument of \p callee is called in
912
+ // / \p callee or any function called by callee.
913
+ static bool isClosureAppliedIn (SILFunction *Callee, unsigned closureArgIdx,
914
+ SmallPtrSetImpl<SILFunction *> &HandledFuncs) {
915
+ // Limit the number of recursive calls to not go into exponential behavior in
916
+ // corner cases.
917
+ const int RecursionBudget = 8 ;
918
+
919
+ SILValue Arg = Callee->getArgument (closureArgIdx);
920
+ for (Operand *ArgUse : Arg->getUses ()) {
921
+ if (auto UserAI = FullApplySite::isa (ArgUse->getUser ())) {
922
+ if (UserAI.getCallee () == Arg)
923
+ return true ;
924
+
925
+ assert (UserAI.isArgumentOperand (*ArgUse) &&
926
+ " any other non-argument operands than the callee?" );
927
+
928
+ SILFunction *ApplyCallee = UserAI.getReferencedFunction ();
929
+ if (ApplyCallee && !ApplyCallee->isExternalDeclaration () &&
930
+ HandledFuncs.count (ApplyCallee) == 0 &&
931
+ HandledFuncs.size () < RecursionBudget) {
932
+ HandledFuncs.insert (ApplyCallee);
933
+ if (isClosureAppliedIn (UserAI.getReferencedFunction (),
934
+ UserAI.getCalleeArgIndex (*ArgUse), HandledFuncs))
935
+ return true ;
936
+ }
937
+ }
938
+ }
939
+ return false ;
940
+ }
941
+
911
942
bool SILClosureSpecializerTransform::gatherCallSites (
912
943
SILFunction *Caller,
913
944
llvm::SmallVectorImpl<ClosureInfo*> &ClosureCandidates,
@@ -1018,43 +1049,23 @@ bool SILClosureSpecializerTransform::gatherCallSites(
1018
1049
if (mayBindDynamicSelf (ApplyCallee))
1019
1050
return CFGChanged;
1020
1051
1021
- // Ok, we know that we can perform the optimization but not whether or
1022
- // not the optimization is profitable. Find the index of the argument
1023
- // corresponding to our partial apply.
1024
- Optional<unsigned > ClosureIndex;
1025
- for (unsigned i = 0 , e = AI.getNumArguments (); i != e; ++i) {
1026
- if (AI.getArgument (i) != Use->get ())
1027
- continue ;
1028
- ClosureIndex = i;
1029
- DEBUG (llvm::dbgs () << " Found callsite with closure argument at "
1030
- << i << " : " << *AI.getInstruction ());
1031
- break ;
1032
- }
1033
-
1034
- // If we did not find an index, there is nothing further to do,
1035
- // continue.
1036
- if (!ClosureIndex.hasValue ())
1052
+ // Check if the closure is passed as an argument (and not called).
1053
+ if (!AI.isArgumentOperand (*Use))
1037
1054
continue ;
1038
1055
1039
- // Make sure that the Closure is invoked in the Apply's callee. We only
1040
- // want to perform closure specialization if we know that we will be
1041
- // able to change a partial_apply into an apply.
1042
- //
1043
- // TODO: Maybe just call the function directly instead of moving the
1044
- // partial apply?
1045
- SILValue Arg = ApplyCallee->getArgument (ClosureIndex.getValue ());
1046
- if (std::none_of (Arg->use_begin (), Arg->use_end (),
1047
- [&Arg](Operand *Op) -> bool {
1048
- auto UserAI = FullApplySite::isa (Op->getUser ());
1049
- return UserAI && UserAI.getCallee () == Arg;
1050
- })) {
1056
+ unsigned ClosureIndex = AI.getCalleeArgIndex (*Use);
1057
+
1058
+ // Ok, we know that we can perform the optimization but not whether or
1059
+ // not the optimization is profitable. Check if the closure is actually
1060
+ // called in the callee (or in a function called by the callee).
1061
+ SmallPtrSet<SILFunction *, 8 > HandledFuncs;
1062
+ if (!isClosureAppliedIn (ApplyCallee, ClosureIndex, HandledFuncs))
1051
1063
continue ;
1052
- }
1053
1064
1054
1065
unsigned firstParamArgIdx =
1055
1066
AI.getSubstCalleeConv ().getSILArgIndexOfFirstParam ();
1056
- assert (ClosureIndex. getValue () >= firstParamArgIdx);
1057
- auto ClosureParamIndex = ClosureIndex. getValue () - firstParamArgIdx;
1067
+ assert (ClosureIndex >= firstParamArgIdx);
1068
+ auto ClosureParamIndex = ClosureIndex - firstParamArgIdx;
1058
1069
1059
1070
auto ParamInfo = AI.getSubstCalleeType ()->getParameters ();
1060
1071
SILParameterInfo ClosureParamInfo = ParamInfo[ClosureParamIndex];
@@ -1097,7 +1108,7 @@ bool SILClosureSpecializerTransform::gatherCallSites(
1097
1108
// Now we know that CSDesc is profitable to specialize. Add it to our
1098
1109
// call site list.
1099
1110
CInfo->CallSites .push_back (
1100
- CallSiteDescriptor (CInfo, AI, ClosureIndex. getValue () ,
1111
+ CallSiteDescriptor (CInfo, AI, ClosureIndex,
1101
1112
ClosureParamInfo, std::move (NonFailureExitBBs)));
1102
1113
}
1103
1114
if (CInfo) {
0 commit comments