@@ -455,6 +455,82 @@ static bool shouldNotSpecialize(SILFunction *Callee, SILFunction *Caller,
455455 return false ;
456456}
457457
458+ // Addressable parameters cannot be dropped because the address may
459+ // escape. They also can't be promoted to direct convention, so there
460+ // is no danger in preserving them.
461+ static bool canConvertArg (CanSILFunctionType substType, unsigned paramIdx,
462+ SILFunction *caller) {
463+ return !substType->isAddressable (paramIdx, caller);
464+ }
465+
466+ // If there is no read from an indirect argument, this argument has to be
467+ // dropped. At the call site the store to the argument's memory location could
468+ // have been removed (based on the callee's memory effects). Therefore,
469+ // converting such an unused indirect argument to a direct argument, would load
470+ // an uninitialized value at the call site. This would lead to verifier errors
471+ // and in worst case to a miscompile because IRGen can implicitly use dead
472+ // arguments, e.g. for getting the type of a class reference.
473+ static bool canDropUnusedArg (ApplySite apply, SILFunction *callee,
474+ CanSILFunctionType substType,
475+ unsigned paramIdx) {
476+ FullApplySite fas = apply.asFullApplySite ();
477+ if (!fas) {
478+ return false ;
479+ }
480+ Operand &op = fas.getOperandsWithoutIndirectResults ()[paramIdx];
481+ return !callee->argumentMayRead (&op, op.get ());
482+ }
483+
484+ static bool isUsedAsDynamicSelf (SILArgument *arg) {
485+ for (Operand *use : arg->getUses ()) {
486+ if (use->isTypeDependent ())
487+ return true ;
488+ }
489+ return false ;
490+ }
491+
492+ static bool canDropMetatypeArg (ApplySite apply, SILFunction *callee,
493+ unsigned paramIdx) {
494+ if (!callee->isDefinition ())
495+ return false ;
496+
497+ unsigned calleeArgIdx =
498+ apply.getSubstCalleeConv ().getSILArgIndexOfFirstParam () + paramIdx;
499+ SILArgument *calleeArg = callee->getArguments ()[calleeArgIdx];
500+
501+ if (isUsedAsDynamicSelf (calleeArg))
502+ return false ;
503+
504+ if (calleeArg->getType ().getASTType ()->hasDynamicSelfType ())
505+ return false ;
506+
507+ // We don't drop metatype arguments of not applied arguments (in case of
508+ // `partial_apply`).
509+ unsigned firstAppliedArgIdx = apply.getCalleeArgIndexOfFirstAppliedArg ();
510+ if (firstAppliedArgIdx > calleeArgIdx)
511+ return false ;
512+
513+ auto mt = calleeArg->getType ().castTo <MetatypeType>();
514+ if (mt->hasRepresentation ()
515+ && mt->getRepresentation () == MetatypeRepresentation::Thin) {
516+ return true ;
517+ }
518+ // If the passed thick metatype value is not a `metatype` instruction
519+ // we don't know the real metatype at runtime. It's not necessarily the
520+ // same as the declared metatype. It could e.g. be an upcast of a class
521+ // metatype.
522+ SILValue callerArg = apply.getArguments ()[calleeArgIdx - firstAppliedArgIdx];
523+ if (isa<MetatypeInst>(callerArg))
524+ return true ;
525+
526+ // But: if the metatype is not used in the callee we don't have to care
527+ // what metatype value is passed. We can just remove it.
528+ if (onlyHaveDebugUses (calleeArg))
529+ return true ;
530+
531+ return false ;
532+ }
533+
458534// / Prepares the ReabstractionInfo object for further processing and checks
459535// / if the current function can be specialized at all.
460536// / Returns false, if the current function cannot be specialized.
@@ -771,7 +847,7 @@ void ReabstractionInfo::createSubstitutedAndSpecializedTypes() {
771847 for (SILParameterInfo PI : SubstitutedType->getParameters ()) {
772848 auto IdxToInsert = IdxForParam;
773849 ++IdxForParam;
774- unsigned argIdx = i++;
850+ unsigned paramIdx = i++;
775851
776852 SILFunctionConventions substConv (SubstitutedType, getModule ());
777853 TypeCategory tc = getParamTypeCategory (PI, substConv, getResilienceExpansion ());
@@ -782,22 +858,14 @@ void ReabstractionInfo::createSubstitutedAndSpecializedTypes() {
782858 case ParameterConvention::Indirect_In_CXX:
783859 case ParameterConvention::Indirect_In:
784860 case ParameterConvention::Indirect_In_Guaranteed: {
785- if (Callee && Apply && dropUnusedArguments) {
786- // If there is no read from an indirect argument, this argument has to
787- // be dropped. At the call site the store to the argument's memory location
788- // could have been removed (based on the callee's memory effects).
789- // Therefore, converting such an unused indirect argument to a direct
790- // argument, would load an uninitialized value at the call site.
791- // This would lead to verifier errors and in worst case to a miscompile
792- // because IRGen can implicitly use dead arguments, e.g. for getting the
793- // type of a class reference.
794- if (FullApplySite fas = Apply.asFullApplySite ()) {
795- Operand &op = fas.getOperandsWithoutIndirectResults ()[argIdx];
796- if (!Callee->argumentMayRead (&op, op.get ())) {
797- droppedArguments.set (IdxToInsert);
798- break ;
799- }
800- }
861+ if (Apply && !canConvertArg (SubstitutedType, paramIdx,
862+ Apply.getFunction ())) {
863+ continue ;
864+ }
865+ if (Callee && Apply && dropUnusedArguments
866+ && canDropUnusedArg (Apply, Callee, SubstitutedType, paramIdx)) {
867+ droppedArguments.set (IdxToInsert);
868+ break ;
801869 }
802870 Conversions.set (IdxToInsert);
803871 if (tc == LoadableAndTrivial)
@@ -822,8 +890,10 @@ void ReabstractionInfo::createSubstitutedAndSpecializedTypes() {
822890 case ParameterConvention::Direct_Unowned:
823891 case ParameterConvention::Direct_Guaranteed: {
824892 CanType ty = PI.getInterfaceType ();
825- if (dropUnusedArguments && isa<MetatypeType>(ty) && !ty->hasArchetype ())
893+ if (dropUnusedArguments && isa<MetatypeType>(ty) && !ty->hasArchetype ()
894+ && Apply && Callee && canDropMetatypeArg (Apply, Callee, paramIdx)) {
826895 droppedArguments.set (IdxToInsert);
896+ }
827897 break ;
828898 }
829899 }
@@ -3211,57 +3281,6 @@ static bool usePrespecialized(
32113281 return false ;
32123282}
32133283
3214- static bool isUsedAsDynamicSelf (SILArgument *arg) {
3215- for (Operand *use : arg->getUses ()) {
3216- if (use->isTypeDependent ())
3217- return true ;
3218- }
3219- return false ;
3220- }
3221-
3222- static bool canDropMetatypeArgs (ApplySite apply, SILFunction *callee) {
3223- if (!callee->isDefinition ())
3224- return false ;
3225-
3226- auto calleeArgs = callee->getArguments ();
3227- unsigned firstAppliedArgIdx = apply.getCalleeArgIndexOfFirstAppliedArg ();
3228- for (unsigned calleeArgIdx = 0 ; calleeArgIdx < calleeArgs.size (); ++calleeArgIdx) {
3229- SILArgument *calleeArg = calleeArgs[calleeArgIdx];
3230- auto mt = calleeArg->getType ().getAs <MetatypeType>();
3231- if (!mt)
3232- continue ;
3233-
3234- if (isUsedAsDynamicSelf (calleeArg))
3235- return false ;
3236-
3237- if (calleeArg->getType ().getASTType ()->hasDynamicSelfType ())
3238- return false ;
3239-
3240- // We don't drop metatype arguments of not applied arguments (in case of `partial_apply`).
3241- if (firstAppliedArgIdx > calleeArgIdx)
3242- return false ;
3243-
3244- if (mt->hasRepresentation () && mt->getRepresentation () == MetatypeRepresentation::Thin)
3245- continue ;
3246-
3247- // If the passed thick metatype value is not a `metatype` instruction
3248- // we don't know the real metatype at runtime. It's not necessarily the
3249- // same as the declared metatype. It could e.g. be an upcast of a class
3250- // metatype.
3251- SILValue callerArg = apply.getArguments ()[calleeArgIdx - firstAppliedArgIdx];
3252- if (isa<MetatypeInst>(callerArg))
3253- continue ;
3254-
3255- // But: if the metatype is not used in the callee we don't have to care
3256- // what metatype value is passed. We can just remove it.
3257- if (callee->isDefinition () && onlyHaveDebugUses (calleeArg))
3258- continue ;
3259-
3260- return false ;
3261- }
3262- return true ;
3263- }
3264-
32653284void swift::trySpecializeApplyOfGeneric (
32663285 SILOptFunctionBuilder &FuncBuilder,
32673286 ApplySite Apply, DeadInstructionSet &DeadApplies,
@@ -3314,8 +3333,7 @@ void swift::trySpecializeApplyOfGeneric(
33143333 FuncBuilder.getModule ().isWholeModule (), Apply, RefF,
33153334 Apply.getSubstitutionMap (), serializedKind,
33163335 /* ConvertIndirectToDirect=*/ true ,
3317- /* dropUnusedArguments=*/
3318- canDropMetatypeArgs (Apply, RefF),
3336+ /* dropUnusedArguments=*/ true ,
33193337 &ORE);
33203338 if (!ReInfo.canBeSpecialized ())
33213339 return ;
0 commit comments