@@ -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 }
@@ -2916,7 +2986,8 @@ static bool createPrespecialized(StringRef UnspecializedName,
29162986 ReabstractionInfo ReInfo (M.getSwiftModule (), M.isWholeModule (), ApplySite (),
29172987 UnspecFunc, Apply.getSubstitutionMap (),
29182988 IsNotSerialized,
2919- /* ConvertIndirectToDirect= */ true , /* dropMetatypeArgs=*/ false );
2989+ /* ConvertIndirectToDirect= */ true ,
2990+ /* dropUnusedArguments=*/ false );
29202991
29212992 if (!ReInfo.canBeSpecialized ())
29222993 return false ;
@@ -3005,7 +3076,7 @@ static bool usePrespecialized(
30053076 funcBuilder.getModule ().isWholeModule (), apply, refF,
30063077 apply.getSubstitutionMap (), IsNotSerialized,
30073078 /* ConvertIndirectToDirect=*/ true ,
3008- /* dropMetatypeArgs =*/ false );
3079+ /* dropUnusedArguments =*/ false );
30093080
30103081 for (auto *SA : refF->getSpecializeAttrs ()) {
30113082 if (!SA->isExported ())
@@ -3149,7 +3220,8 @@ static bool usePrespecialized(
31493220 funcBuilder.getModule ().getSwiftModule (),
31503221 funcBuilder.getModule ().isWholeModule (), apply, refF, newSubstMap,
31513222 apply.getFunction ()->getSerializedKind (),
3152- /* ConvertIndirectToDirect=*/ true , /* dropMetatypeArgs=*/ false , nullptr );
3223+ /* ConvertIndirectToDirect=*/ true ,
3224+ /* dropUnusedArguments=*/ false , nullptr );
31533225
31543226 if (layoutReInfo.getSpecializedType () == reInfo.getSpecializedType ()) {
31553227 layoutMatches.push_back (
@@ -3209,57 +3281,6 @@ static bool usePrespecialized(
32093281 return false ;
32103282}
32113283
3212- static bool isUsedAsDynamicSelf (SILArgument *arg) {
3213- for (Operand *use : arg->getUses ()) {
3214- if (use->isTypeDependent ())
3215- return true ;
3216- }
3217- return false ;
3218- }
3219-
3220- static bool canDropMetatypeArgs (ApplySite apply, SILFunction *callee) {
3221- if (!callee->isDefinition ())
3222- return false ;
3223-
3224- auto calleeArgs = callee->getArguments ();
3225- unsigned firstAppliedArgIdx = apply.getCalleeArgIndexOfFirstAppliedArg ();
3226- for (unsigned calleeArgIdx = 0 ; calleeArgIdx < calleeArgs.size (); ++calleeArgIdx) {
3227- SILArgument *calleeArg = calleeArgs[calleeArgIdx];
3228- auto mt = calleeArg->getType ().getAs <MetatypeType>();
3229- if (!mt)
3230- continue ;
3231-
3232- if (isUsedAsDynamicSelf (calleeArg))
3233- return false ;
3234-
3235- if (calleeArg->getType ().getASTType ()->hasDynamicSelfType ())
3236- return false ;
3237-
3238- // We don't drop metatype arguments of not applied arguments (in case of `partial_apply`).
3239- if (firstAppliedArgIdx > calleeArgIdx)
3240- return false ;
3241-
3242- if (mt->hasRepresentation () && mt->getRepresentation () == MetatypeRepresentation::Thin)
3243- continue ;
3244-
3245- // If the passed thick metatype value is not a `metatype` instruction
3246- // we don't know the real metatype at runtime. It's not necessarily the
3247- // same as the declared metatype. It could e.g. be an upcast of a class
3248- // metatype.
3249- SILValue callerArg = apply.getArguments ()[calleeArgIdx - firstAppliedArgIdx];
3250- if (isa<MetatypeInst>(callerArg))
3251- continue ;
3252-
3253- // But: if the metatype is not used in the callee we don't have to care
3254- // what metatype value is passed. We can just remove it.
3255- if (callee->isDefinition () && onlyHaveDebugUses (calleeArg))
3256- continue ;
3257-
3258- return false ;
3259- }
3260- return true ;
3261- }
3262-
32633284void swift::trySpecializeApplyOfGeneric (
32643285 SILOptFunctionBuilder &FuncBuilder,
32653286 ApplySite Apply, DeadInstructionSet &DeadApplies,
@@ -3312,7 +3333,7 @@ void swift::trySpecializeApplyOfGeneric(
33123333 FuncBuilder.getModule ().isWholeModule (), Apply, RefF,
33133334 Apply.getSubstitutionMap (), serializedKind,
33143335 /* ConvertIndirectToDirect=*/ true ,
3315- /* dropMetatypeArgs =*/ canDropMetatypeArgs (Apply, RefF) ,
3336+ /* dropUnusedArguments =*/ true ,
33163337 &ORE);
33173338 if (!ReInfo.canBeSpecialized ())
33183339 return ;
0 commit comments